﻿using AutoMapper;
using Lanbt.Core.Entity.Dto;
using Lanbt.Core.Entity.Dto.lanbt_power;
using Lanbt.Core.Entity.Dto.lanbt_system_config;
using Lanbt.Core.Entity.EntityDB;
using Lanbt.Core.Entity.Enums;
using Lanbt.Core.Repository.SqlService.IRepository;
using Lanbt.Core.Service.SqlService.IService;
using Lanbt.Core.Utility.ExceptionExtent;
using Lanbt.Core.Utility.Extent;
using SqlSugar.Extensions;

namespace Lanbt.Core.Service.SqlService
{
    public class PowerService : ServiceBase,IPowerService
    {
        private readonly IPowerRepository _powerRepository;
        private readonly IRoleRepository _roleRepository;

        private readonly IMapper _mapper;

        public PowerService(IPowerRepository powerRepository,IMapper mapper, IRoleRepository roleRepository)
        {
            _powerRepository = powerRepository;
            _mapper = mapper;
            _roleRepository = roleRepository;
        }

        public async Task<ResultOutput<lanbt_power>> GetPowerById(string id)
        {
            var res = new ResultOutput<lanbt_power>();
            var power = await _powerRepository.FirstOrDefault(id);
            if (power.IsNull())
            {
                return res.AddError("权限不存在，请刷新重试");
            }
            return res.ResultInput(power);
        }

        public async Task<PagesResultOutput<QueryPagedPowerListOutput>> QueryPagedPowerList(QueryPagedPowerListInput input)
        {
            var res = new PagesResultOutput<QueryPagedPowerListOutput>();

            var where = Extensions.Load<lanbt_power>();

            if (input.Name.IsNotNullOrEmpty())
            {
                where = where.And(q => q.Name.Contains(input.Name.Trim()));
            }

            if(input.ParentID.IsNotNullOrEmpty())
            {
                if(input.ParentID.ObjToInt() == 0)
                    where = where.And(q => q.ParentID == input.ParentID.ObjToInt());
                if(input.ParentID.ObjToInt() > 0)
                    where = where.And(q => q.Path.Contains(input.ParentID.ToString()));
            }

            if (input.MenuCode.IsNotNullOrEmpty())
            {
                where = where.And(q => q.MenuCode.ToLower().Contains(input.MenuCode.ToTrimAndLower()));
            }

            if(input.PowerType != PowerType.None)
            {
                where = where.And(q => q.PowerType == input.PowerType);
            }

            if(input.Status != null)
            {
                where = where.And(q => q.IsEnable == input.Status);
            }
            if(input.ShowType != null)
            {
                where = where.And(q => q.IsMenuShow == input.ShowType);
            }

            var paged = await _powerRepository.QueryToPageListOrderBy(input.PageIndex, input.PageSize, where, e => e.Sort);

            var list = _mapper.Map<List<QueryPagedPowerListOutput>>(paged.Item2);

            foreach (var item in list)
            {
                if(item.ParentID == 0)
                {
                    item.ParentName = "根目录";
                }
                else
                {
                    var power = await _powerRepository.FirstOrDefault(q => q.Sort == item.ParentID);
                    if (power.IsNull())
                    {
                        return res.AddError($"【{item.Name}】父级节点未找到！");
                    }
                    item.ParentName = power.Name;
                }
            }

            return new PagesResultOutput<QueryPagedPowerListOutput>(paged.Item1, list);
        }

        public async Task<ResultOutput<List<XM_SelectOutput>>> QuerySelectList()
        {
            List<XM_SelectOutput> result = new List<XM_SelectOutput>();
            result.Add(new XM_SelectOutput
            {
                name = "根目录",
                selected = false,
                value = "0"
            });
            var powerList = await _powerRepository.Query(q=>!q.IsDelete && (q.PowerType == PowerType.Folder || q.PowerType == PowerType.Html));
            foreach (var item in powerList)
            {
                result.Add(new XM_SelectOutput
                {
                    name = item.Name,
                    selected = false,
                    value = item.Sort.ToString()
                });
            }

            return new ResultOutput<List<XM_SelectOutput>>(result);
        }

        public async Task<IList<TreeData>> QueryPowerTreeData()
        {
            var result = new List<TreeData>();

            var powerList = await _powerRepository.QueryAllByEnable();
            //获取根目录
            var roots = powerList.Where(q => q.ParentID == 0);

            foreach (var root in roots)
            {
                var tree = new TreeData
                {
                    Title = root.Name + '-' +root.PowerType.Description(),
                    Id = root.Sort.ToString(),
                };
                await RecursionTreeData(tree.Children, root.Sort,powerList);
                result.Add(tree);
            }
            return result;
        }

        /// <summary>
        /// 递归树形数据
        /// </summary>
        /// <param name="childrens"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        private async Task RecursionTreeData(List<TreeData> childrens,int sort,IList<lanbt_power> powerList)
        {
            var result = new List<TreeData>();

            var powerClidrens = powerList.Where(q => q.ParentID == sort);

            foreach (var power in powerClidrens)
            {
                var tree = new TreeData
                {
                    Title = power.Name + '-' + power.PowerType.Description(),
                    Id = power.Sort.ToString(),
                };
                await RecursionTreeData(tree.Children, power.Sort,powerList);
                result.Add(tree);
            }

            childrens.AddRange(result);
        }

        public async Task<ResultOutput<List<QueryMenuListOutput>>> QueryMenuList()
        {
            var res = new ResultOutput<List<QueryMenuListOutput>>();
            var currentUserInfo = await GetCurrentUserInfo();
            //超级管理员取所有菜单
            IList<lanbt_power> powerList = await _powerRepository.QueryMenuByShow();
            //不是超管则按权限来
            if (!currentUserInfo.IsAdmin)
            {
                List<string> powerIds = new List<string>();
                //取当前用户的角色，所有角色菜单的交集
                foreach (string roleId in currentUserInfo.RoleIds)
                {
                    var role = await _roleRepository.FirstOrDefault(roleId);
                    if(role.IsNotNull() && role.PowerIds.IsNotNullOrEmpty())
                    {
                        var powerIdArr = role.PowerIds.Split(',');
                        powerIds = powerIds.Union(powerIdArr).ToList();//并集
                    }
                }
                powerList = powerList.Where(q=> powerIds.Contains(q.Sort.ToString())).ToList();
            }
            var roots = powerList.Where(q => q.ParentID == 0);
            res.Result = new List<QueryMenuListOutput>();
            foreach (var item in roots)
            {
                QueryMenuListOutput queryMenuListOutput = new QueryMenuListOutput()
                {
                    Id = item.ID,
                    Title = item.Name,
                    Icon = item.IconUrl,
                    powerType = item.PowerType,
                    Src = item.LineUrl
                };
                queryMenuListOutput.Childrens = await RecursionMenuList(item, powerList);
                res.Result.Add(queryMenuListOutput);
            }
            return res;
        }

        /// <summary>
        /// 递归菜单列表
        /// </summary>
        /// <param name="power"></param>
        /// <param name="powerList"></param>
        /// <returns></returns>
        private async Task<List<QueryMenuListOutput>> RecursionMenuList(lanbt_power power, IList<lanbt_power> powerList)
        {
            List<QueryMenuListOutput> queryMenuListOutputs= new List<QueryMenuListOutput>();
            var childrens = powerList.Where(q => q.ParentID == power.Sort);
            foreach (var item in childrens)
            {
                QueryMenuListOutput queryMenuListOutput = new QueryMenuListOutput()
                {
                    Id = item.ID,
                    Title = item.Name,
                    Icon = item.IconUrl,
                    powerType = item.PowerType,
                    Src = item.LineUrl
                };
                queryMenuListOutput.Childrens = await RecursionMenuList(item, powerList);
                queryMenuListOutputs.Add(queryMenuListOutput);
            }
            return queryMenuListOutputs;
        }

        public async Task<ResultOutput> InsertPower(InsertPowerInput input)
        {
            var res = new ResultOutput();
            var insert = _mapper.Map<lanbt_power>(input);

            if(insert.ParentID == 0)
            {
                insert.Level = 1;
                insert.Path = String.Empty;
            }
            else
            {
                var power = await _powerRepository.FirstOrDefault(q => q.Sort == insert.ParentID);
                if(power == null)
                {
                    return res.AddError("未查询到对应的父节点");
                }
                insert.Level = power.Level + 1;
                if (power.Path.IsNotNullOrEmpty())
                {
                    insert.Path = power.Path + "," + power.Sort;
                }
                else
                {
                    insert.Path = power.Sort.ToString();
                }
            }

            insert.Sort = await _powerRepository.Count(true) + 1;
            insert.IsEnable = true;//默认启用
            if(insert.PowerType == PowerType.Folder || insert.PowerType == PowerType.Html)
            {
                insert.IsMenuShow = true;//文件夹和html默认显示
            }
            var id = await _powerRepository.InsertOne(insert);
            return res;
        }

        public async Task<ResultOutput> DeletePowerById(string id)
        {
            var res = new ResultOutput();
            var power = await _powerRepository.FirstOrDefault(id);
            if (power.IsNull())
            {
                return res.AddError("权限不存在，请刷新重试");
            }
            await _powerRepository.Delete_false(id);

            var childrens = await _powerRepository.Query(q => q.ParentID == power.Sort);
            foreach (var child in childrens)
            {
                await DeletePowerById(child.ID);
            }

            return res;
        }

        public async  Task<ResultOutput> DeletePowerByIds(string[] ids)
        {
            var res = new ResultOutput();
            foreach (var id in ids)
            {
                await DeletePowerById(id);
            }
            return res;
        }

        public async Task<ResultOutput> UpdatePower(UpdatePowerInput input)
        {
            var res = new ResultOutput();
            var power = await _powerRepository.FirstOrDefault(input.ID);
            if (power.IsNull())
            {
                return res.AddError("权限不存在，请刷新重试");
            }
            IList<lanbt_power> childrens = await _powerRepository.Query(q => q.ParentID == power.Sort);
            if(input.PowerType == PowerType.Button && childrens.Count > 0)
            {
                return res.AddError("该权限有子集，权限类型不能改为按钮");
            }

            //是否修改了父级ID
            bool updateParentID = power.ParentID != input.ParentID;
            power.Name = input.Name;
            power.MenuCode = input.MenuCode;
            power.ParentID = (int)input.ParentID;
            power.PowerType = (PowerType)input.PowerType;
            power.IconUrl = input.IconUrl;
            power.LineUrl = input.LineUrl;
            power.Descript = input.Descript;

            if (power.ParentID == 0)
            {
                power.Level = 1;
                power.Path = String.Empty;
            }
            else
            {
                var parent = await _powerRepository.FirstOrDefault(q => q.Sort == power.ParentID);
                if (parent == null)
                {
                    return res.AddError("未查询到对应的父节点");
                }
                power.Level = parent.Level + 1;
                if (parent.Path.IsNotNullOrEmpty())
                {
                    power.Path = parent.Path + "," + parent.Sort;
                }
                else
                {
                    power.Path = parent.Sort.ToString();
                }
            }
            power.IsEnable = true;//默认启用
            if (power.PowerType == PowerType.Folder || power.PowerType == PowerType.Html)
            {
                power.IsMenuShow = true;//文件夹和html默认显示
            }
            await _powerRepository.UpdateOne(power);

            //若修改了，子集也要修改
            if (updateParentID)
            {
                //修改子集Path
                foreach (var child in childrens)
                {
                    await UpdatePath(child.ID);
                }
            }

            return res;
        }

        /// <summary>
        /// 递归修改Path
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private async Task UpdatePath(string id)
        {
            var power = await _powerRepository.FirstOrDefault(id);
            if (power.ParentID == 0)
            {
                power.Level = 1;
                power.Path = String.Empty;
            }
            else
            {
                var parent = await _powerRepository.FirstOrDefault(q => q.Sort == power.ParentID);
                power.Level = parent.Level + 1;
                if (parent.Path.IsNotNullOrEmpty())
                {
                    power.Path = parent.Path + "," + parent.Sort;
                }
                else
                {
                    power.Path = parent.Sort.ToString();
                }
            }
            await _powerRepository.UpdateOne(power);
            var childrens = await _powerRepository.Query(q => q.ParentID == power.Sort);
            foreach (var child in childrens)
            {
                await UpdatePath(child.ID);
            }
        }

        public async Task<ResultOutput> UpdateMenuShowOrHide(string id)
        {
            lanbt_power power = await _powerRepository.FirstOrDefault(id);
            if (power.IsNull())
            {
                throw new LanbtException(ExceptionModel.ENTITY_EXISTEN, "权限");
            }
            if (power.PowerType == PowerType.Power || power.PowerType == PowerType.Button || power.PowerType == PowerType.None)
            {
                throw new LanbtException(ExceptionModel.INFO, "【按钮、权限】不允许设置");
            }
            power.IsMenuShow = !power.IsMenuShow;
            await _powerRepository.UpdateOne(power);
            //如果是 显示菜单，查询他的上级是否是显示状态，若不是则设置为显示状态
            if (power.IsMenuShow && power.Path.IsNotNullOrEmpty())
            {
                var sorts = power.Path.Split(',').ToList();
                var powers = await _powerRepository.Query(q => sorts.Contains(q.Sort.ToString()) && (q.PowerType == PowerType.Folder || q.PowerType == PowerType.Html));
                if (powers.Count > 0)
                {
                    foreach (var item in powers)
                    {
                        item.IsMenuShow = power.IsMenuShow;
                    }
                    await _powerRepository.UpdateMany(powers);
                }
            }
            //如果是隐藏，则连带隐藏他的子集
            else
            {
                List<lanbt_power> lanbt_Powers = new List<lanbt_power>();
                await RecursionMenuChildren(power.Sort, lanbt_Powers);
                lanbt_Powers.ForEach(item =>
                {
                    item.IsMenuShow = power.IsMenuShow;
                });
                await _powerRepository.UpdateMany(lanbt_Powers);
            }
            return new ResultOutput();
        }

        public async Task<ResultOutput> UpdateMenuEnable(string id)
        {
            lanbt_power power = await _powerRepository.FirstOrDefault(id);
            if (power.IsNull())
            {
                throw new LanbtException(ExceptionModel.ENTITY_EXISTEN, "权限");
            }
            power.IsEnable = !power.IsEnable;
            await _powerRepository.UpdateOne(power);
            //如果是 启用菜单，查询他的上级是否是显示状态，若不是则设置为显示状态
            if (power.IsEnable && power.Path.IsNotNullOrEmpty())
            {
                var sorts = power.Path.Split(',').ToList();
                var powers = await _powerRepository.Query(q => sorts.Contains(q.Sort.ToString()) && (q.PowerType == PowerType.Folder || q.PowerType == PowerType.Html));
                if (powers.Count > 0)
                {
                    foreach (var item in powers)
                    {
                        item.IsEnable = power.IsEnable;
                    }
                    await _powerRepository.UpdateMany(powers);
                }
            }
            //如果是隐藏，则连带隐藏他的子集
            else
            {
                List<lanbt_power> lanbt_Powers = new List<lanbt_power>();
                await RecursionMenuChildren(power.Sort, lanbt_Powers);
                lanbt_Powers.ForEach(item =>
                {
                    item.IsEnable = power.IsEnable;
                });
                await _powerRepository.UpdateMany(lanbt_Powers);
            }
            return new ResultOutput();
        }

        /// <summary>
        /// 递归查询菜单子集(不包含【按钮、权限】)
        /// </summary>
        /// <param name="id"></param>
        /// <param name="lanbt_Powers"></param>
        /// <returns></returns>
        private async Task RecursionMenuChildren(int sort,List<lanbt_power> lanbt_Powers)
        {
            var powerlist = await _powerRepository.Query(q => q.ParentID == sort && q.PowerType != PowerType.Button && q.PowerType != PowerType.Power);
            foreach (var item in powerlist)
            {
                await RecursionMenuChildren(item.Sort, lanbt_Powers);
            }
            lanbt_Powers.AddRange(powerlist);
        }
    }
}
